<?php

namespace Queue\Manager;

use Queue\Interfaces\{
    QueueManagerInterface,
    TaskInterface,
    ProcessInvokerInterface,
};

final class AsyncQueueManager implements QueueManagerInterface
{
    private \SplQueue $waitingTaskQueue;

    private ProcessInvokerInterface $processInvoker;

    private array $runningTasks;

    private string $worker;

    public function __construct(ProcessInvokerInterface $processInvoker)
    {
        $this->taskQueue = new \SplQueue();
        $this->taskQueue->setIteratorMode(\SplDoublyLinkedList::IT_MODE_DELETE);
        $this->worker = \realpath(__DIR__ . "/../../../bin/worker.php");
        $this->processInvoker = $processInvoker;
    }

    public function enqueue(TaskInterface $task): void
    {
        $this->taskQueue->enqueue($task);
    }

    public function run(): void
    {
        while (!$this->taskQueue->isEmpty()) {
            /** @var TaskInterface $task */
            $task = $this->taskQueue->dequeue();
            $taskPid = $this->processInvoker->run($task, $this->worker);
            $this->runningTasks[$taskPid] = $task;
        }
    }

    public function getTaskStatuses(): array
    {
        $statuses = [];

        foreach ($this->taskQueue as $task) {
            $statuses[] = [
                'pid' => -1,
                'task' => \get_class($task),
                'is_running' => false,
            ];
        }

        foreach ($this->runningTasks as $pid => $task) {
            $statuses[] = [
                'pid' => $pid,
                'task' => \get_class($task),
                'is_running' => $this->processInvoker->isRunning($pid),
            ];
        }

        return $statuses;
    }
}
